﻿namespace eventBusDemo
{
    public interface IEvent
    {
        DateTime OccurredOn { get; }

    }

    public class OrderCreatedEvent : IEvent
    {
        public DateTime OccurredOn { get; } = DateTime.UtcNow;
        public string OrderId { get; }

        public OrderCreatedEvent(string orderId)
        {
            OrderId = orderId;
        }
    }

    public interface IEventHandler<in TEvent> where TEvent : IEvent
    {
        Task Handle(TEvent @event);
    }

    public interface IEventBus
    {
        void Publish<TEvent>(TEvent @event) where TEvent : IEvent;
        void Subscribe<TEvent, THandler>()
            where TEvent : IEvent
            where THandler : IEventHandler<TEvent>;
    }

    public class InMemoryEventBus : IEventBus
    {
        private readonly Dictionary<Type, List<Type>> _handlers = new();
        private readonly IServiceProvider _serviceProvider;

        public InMemoryEventBus(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }

        public void Publish<TEvent>(TEvent @event) where TEvent : IEvent
        {
            if (_handlers.TryGetValue(typeof(TEvent), out var handlerTypes))
            {
                foreach (var handlerType in handlerTypes)
                {
                    var handler = _serviceProvider.GetService(handlerType) as IEventHandler<TEvent>;
                    if (handler != null)
                    {
                        handler.Handle(@event).Wait();
                    }
                    else
                    {
                        Console.WriteLine($"Handler for {handlerType.Name} not found.");
                    }
                }
            }
            else
            {
                Console.WriteLine($"No handlers registered for event type {typeof(TEvent).Name}.");
            }
        }

        public void Subscribe<TEvent, THandler>()
     where TEvent : IEvent
     where THandler : IEventHandler<TEvent>
        {
            var eventType = typeof(TEvent);
            var handlerType = typeof(THandler);

            if (!_handlers.ContainsKey(eventType))
            {
                _handlers[eventType] = new List<Type>();
            }

            if (!_handlers[eventType].Contains(handlerType))
            {
                _handlers[eventType].Add(handlerType);
            }
        }
    }
    public class OrderCreatedEventHandler : IEventHandler<OrderCreatedEvent>
    {
        public Task Handle(OrderCreatedEvent @event)
        {
            Console.WriteLine($"Order created with ID: {@event.OrderId}");
            return Task.CompletedTask;
        }
    }

}
